﻿using System;
using System.Collections.Generic;
using System.Text;

namespace SerialTool
{
    public class Frame
    {
        /*
         * 多余的10已经去掉
         * 数据格式 : 帧头 | LEN:MSB first|src addr|src len|tgt addr|tgt len|tyep|cmd|data:LEN-8|CRC       |F tail|
         * --------------------------------------------------------------------------------------------------------
         *           10 02 | -- --        | --     | 00    |--      |00     |--  |-- | ......   |00 00     |10 03 |
         */
        private byte[] data;
        //with source address length and target address length set to 0;
        private const byte FRAME_MIN_LEN = 14;
        private const byte FRAME_SRC_OFFSET = 4;
        private const byte FRAME_SRCLEN_OFFSET = 5;
        private const byte FRAME_TGT_OFFSET = 6;
        private const byte FRAME_TGTLEN_OFFSET = 7;
        private const byte FRAME_TYPE_OFFSET = 8;
        private const byte FRAME_CMD_OFFSET = 9;
        private const byte FRAME_DATA_OFFSET = 10;

        public Frame(byte[] frame, int length)
        {
            if (frame == null) 
                return;
            if (length <= 0) 
                return;
            if (length > frame.Length) 
                return;
            if (length < FRAME_MIN_LEN) 
                return;

            data = new byte[length];
            Array.Copy(frame, data, length);
        }

        /// <summary>
        /// 源端口号
        /// </summary>
        public byte SrcPort
        {
            get
            {
                if (data == null)
                    return 0;
                return data[FRAME_SRC_OFFSET];
                
            }
        }

        /// <summary>
        /// 目的端口号
        /// </summary>
        public byte DestPort
        {
            get
            {
                if (data == null)
                    return 0;
                int SrcAddrLen = data[FRAME_SRCLEN_OFFSET];
                return data[FRAME_TGT_OFFSET + SrcAddrLen];
            }
        }

        /// <summary>
        /// 事务
        /// </summary>
        public byte cmdType
        {
            get
            {
                if (data == null)
                    return 0;
                int SrcAddrLen = data[FRAME_SRCLEN_OFFSET];
                int DstAddrLen = data[FRAME_TGTLEN_OFFSET + SrcAddrLen];

                return data[FRAME_TYPE_OFFSET + SrcAddrLen + DstAddrLen];
            }
        }

        /// <summary>
        /// 命令
        /// </summary>
        public byte Cmd
        {
            get
            {
                if (data == null)
                    return 0;
                int SrcAddrLen = data[FRAME_SRCLEN_OFFSET];
                int DstAddrLen = data[FRAME_TGTLEN_OFFSET + SrcAddrLen];

                return data[FRAME_CMD_OFFSET + SrcAddrLen + DstAddrLen];
            }
        }

        /// <summary>
        /// 数据
        /// </summary>
        public byte[] cmdData
        {
            get
            {
                if (data == null)
                    return null;
                int SrcAddrLen = data[FRAME_SRCLEN_OFFSET];
                int DstAddrLen = data[FRAME_TGTLEN_OFFSET + SrcAddrLen];

                byte[] buf = new byte[data.Length - FRAME_MIN_LEN - SrcAddrLen - DstAddrLen];
                Array.Copy(data, FRAME_DATA_OFFSET + SrcAddrLen + DstAddrLen, buf, 0, buf.Length);
                return buf;
            }
        }


        public byte[] RawData
        {
            get { return data; }
        }

        public string ToStringX2(int markNum)
        {
            if (data == null)
                return "wrong frame structre";

            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < data.Length; i++)
            {
                string mark = " ";
                if (i+2 == markNum && markNum<= data.Length)
                    mark = "[";
                if (i+1 == markNum && markNum > 0)
                    mark = "]";
                sb.Append(data[i].ToString("X2") + mark);
            }

            return sb.ToString();
        }



    }
}
